﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Microsoft.Win32;
using Oxage.Common;

namespace Oxage
{
	public class Profile : IEnumerable
	{
		#region Members
		private string name = null;
		private Dictionary<string, string> ht = null;
		#endregion

		#region Constructor
		public Profile()
		{
			this.name = Guid.NewGuid().ToString();
			this.ht = new Dictionary<string, string>();
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets a value indicating whether the profile is from left panel otherwise it is from right.
		/// </summary>
		//public bool IsLeft
		//{
		//  get;
		//  set;
		//}

		/// <summary>
		/// Gets a unique profile name that appears in registry.
		/// </summary>
		public string Name
		{
			get
			{
				if (string.IsNullOrEmpty(this.name))
				{
					return "Unknown";
				}
				return this.name;
			}
			protected set
			{
				this.name = value;
			}
		}

		/// <summary>
		/// Gets a relative profile registry path.
		/// </summary>
		protected string ProfilePath
		{
			get
			{
				return "Profiles\\" + name + "\\";
			}
		}

		/// <summary>
		/// Gets or sets a value for the key.
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		public string this[string key]
		{
			get
			{
				return this.ht.ContainsKey(key) ? this.ht[key] : null;
			}
			set
			{
				if (value != null)
				{
					if (this.ht.ContainsKey(key))
					{
						//Update
						this.ht[key] = value;
					}
					else
					{
						//Insert
						this.ht.Add(key, value);
					}
				}
				else
				{
					//Remove if value is null and hashtable contains the key
					if (this.ht.ContainsKey(key))
					{
						this.ht.Remove(key);
					}
				}
			}
		}
		#endregion

		#region Public methods
		/// <summary>
		/// Loads profile values from Windows registry.
		/// </summary>
		/// <param name="name"></param>
		public void Load(string name, string panel)
		{
			if (string.IsNullOrEmpty(name))
			{
				throw new ArgumentException("Value cannot be null or empty!", "name");
			}

			this.ht.Clear();
			this.Name = name;
			var list = Config.GetKeys(this.ProfilePath);

			foreach (string key in list)
			{
				if (key.Length > 0 && key.StartsWith(panel))
				{
					string value = null;
					Config.Get(this.ProfilePath + key, out value);
					this[key.Substring(1)] = value;
				}
			}
		}

		/// <summary>
		/// Saves profile values to Windows registry.
		/// </summary>
		/// <param name="name"></param>
		public void Save(string name, string panel)
		{
			this.Name = name;
			foreach (string key in this)
			{
				if (this[key] != null)
				{
					Config.Set(this.ProfilePath + panel + key, this[key]);
				}
			}
		}

		/// <summary>
		/// Gets a profile name. Used to display name in ComboBox.
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			return this.name;
		}
		#endregion

		#region Static methods
		/// <summary>
		/// Gets a list of available profiles.
		/// </summary>
		/// <returns>Returns a list of filled Profile instances.</returns>
		public static List<string> GetProfileNames()
		{
			List<string> items = new List<string>();

			try
			{
				string path = Path.Combine(Config.RegistryRootPath, "Profiles");
				RegistryKey reg = Registry.CurrentUser.OpenSubKey(path);
				if (reg != null)
				{
					string[] keys = reg.GetSubKeyNames();
					foreach (string key in keys)
					{
						items.Add(key);
					}
				}
			}
			catch (Exception ex)
			{
				Logger.Log(new Exception("An error occured while trying to get a list of profiles.", ex));
			}

			return items;
		}

		/// <summary>
		/// Deletes an existing profile.
		/// </summary>
		/// <param name="profile">Profile instance.</param>
		/// <returns>Returns true on success.</returns>
		public static bool Delete(string name)
		{
			bool result = false;

			try
			{
				string path = Path.Combine(Config.RegistryRootPath, "Profiles");
				RegistryKey reg = Registry.CurrentUser.OpenSubKey(path, true);
				if (reg != null)
				{
					reg.DeleteSubKey(name);
					return true;
				}
			}
			catch (Exception ex)
			{
				Logger.Log(new Exception("Cannot delete a profile: " + name, ex));
			}

			return result;
		}

		/// <summary>
		/// Merges the specified profiles together into one profile. Every next profile has higher priority - override value of previous profile.
		/// </summary>
		/// <param name="profiles"></param>
		/// <returns></returns>
		public static Profile Merge(params Profile[] profiles)
		{
			Profile profile = new Profile();

			if (profiles != null && profiles.Length > 0)
			{
				foreach (var p in profiles)
				{
					if (p != null)
					{
						foreach (string key in p)
						{
							profile[key] = p[key];
						}
					}
				}
			}

			return profile;
		}
		#endregion

		#region IEnumerable Members
		public IEnumerator GetEnumerator()
		{
			return this.ht.Keys.GetEnumerator();
		}
		#endregion
	}
}
